<?php

namespace coreapi\extensions\db;

use yii;
use yii\base\Model;


/**
 * MySQL数据库操作基础模型
 * @author martinzhang
 */
class ZDB extends Model{


	/**
	 * 插入一条数据
	 * @param object $tabObj    表对象
	 * @param array  $arrParams 字段参数
	 * @return array 返回数组
	 *         status=0   message=插入成功    data=新插入数据的主键Id
	 *         status=8   message=插入失败    data=0
	 * @author martinzhang
	 */
	public static function insert($tabObj, $arrParams){
	
		//拼装数据对象属性值
		try {
			foreach($arrParams as $k=>$v){
				if($v===''){
					continue 1;		//无视空值
				}else{
					$tabObj->$k = trim($v);
				}
			}		
	
		} catch (\Exception $e) {			
			if(preg_match("/Setting\s+unknown\s+property:.*::(.*?)$/i", $e->getMessage(), $matches)){				
				$status = 1363;
				$msg    = "字段名{$matches[1]}未知";
			}else{
				$status = $e->getCode();
				$msg    = $e->getMessage();
			}
			return ['status'=>$status, 'msg'=>$msg, 'data'=>[]];
		}
	
		//尝试插入
		try {
			$res = $tabObj->insert();
			if($res){
				//插入成功
				return ['status'=>0, 'msg'=>'ok', 'data'=>['pkid'=>\Yii::$app->db->getLastInsertID()]];
			}else{
				//插入失败
				return ['status'=>8, 'msg'=>'数据插入失败', 'data'=>[]];
			}
			 
		} catch (\Exception $e) {
			if(preg_match("/Field\s+'(.*?)'\s+doesn't\s+have\s+a\s+default\s+value/i", $e->getMessage(), $matches)){
				$status = 1364;
				$msg    = "字段{$matches[1]}未赋值";				
			}elseif(preg_match("/Duplicate\s+entry\s+'(.*?)'\s+for\s+key\s+'(.*?)'/i", $e->getMessage(), $matches)){
				$status = 23000;
				$msg    = "唯一键字段'{$matches[1]}'记录值已存在";
			}else{
				$status = $e->getCode();
				$msg    = $e->getMessage();
			}			
			return ['status'=>$status, 'msg'=>$msg, 'data'=>[]];
		}
		 
	}	

	/**
	 * 保存一条数据(按主键断定，无则插入，有则更新)
	 * @param  Object $tabObj    表对象
	 * @param  array  $arrParams 字段参数
	 * @return array  返回数组   data同时返回"pkid"和"affected"两个值
	 * @author martinzhang
	 */
	public static function save($tabObj, $arrParams){
		$pkName = $tabObj->primaryKey()[0];
		if(array_key_exists($pkName, $arrParams) && $arrParams[$pkName] > 0){
			//主键存在，更新，按主键查询此条数据
			$rowObj = $tabObj->findOne($arrParams[$pkName]);
			if($rowObj!=null){
				$action = 'update';
			}else{
				$rowObj = $tabObj;
				$action = 'insert';
			}
			
		}else{
			//主键不存在，新插入
			$rowObj = $tabObj;
			$action = 'insert';
		}		

		//拼装数据对象属性值
		try {
			foreach($arrParams as $k=>$v){				
				if($v===''){
					if($action == 'insert'){
						continue 1;			//无视空值
					}elseif($action == 'update'){
						$rowObj->$k = NULL;	//无视空值
					}					
				}else{
					$rowObj->$k = trim($v);
				}
			}
	
		} catch (\Exception $e) {
			if(preg_match("/Setting\s+unknown\s+property:.*::(.*?)$/i", $e->getMessage(), $matches)){
				$status = 1363;
				$msg    = "字段名{$matches[1]}未知";
			}else{
				$status = $e->getCode();
				$msg    = $e->getMessage();
			}
			return ['status'=>$status, 'msg'=>$msg, 'data'=>[]];			
		}		
		
	
		//尝试保存
		try {
			$res = $rowObj->save();
			if($res){
				//保存成功
				if($action=='update'){
					$data = ['pkid'=>\Yii::$app->db->getLastInsertID(), 'affected'=>1];
				}elseif($action=='insert'){
					$data = ['pkid'=>\Yii::$app->db->getLastInsertID(), 'affected'=>0];
				}
				return ['status'=>0, 'msg'=>'ok', 'data'=>$data];
				
			}else{
				//保存失败
				return ['status'=>8, 'msg'=>'数据插入失败', 'data'=>[]];
			}
			 
		} catch (\Exception $e) {
			if(preg_match("/Field\s+'(.*?)'\s+doesn't\s+have\s+a\s+default\s+value/i", $e->getMessage(), $matches)){
				$status = 1364;
				$msg    = "字段名{$matches[1]}未赋值";
			}else{
				$status = $e->getCode();
				$msg    = $e->getMessage();
			}
			return ['status'=>$status, 'msg'=>$msg, 'data'=>[]];
		}
		 
	}
	
	/**
	 * 【真删】删除指定条件数据
	 * @param object $tabObj 表对象
	 * @param array $where   删除条件
	 * @return int  返回数组 返回实际物理删除行数
	 * @author martinzhang
	 */
	public static function deleteTrue($tabObj, $where){
		if(empty($where)){
			return ['status'=>3, 'msg'=>'[内部错误]查询/更新/删除条件不可为空', 'data'=>[]];
		}
		if(!is_array($where)){
			return ['status'=>11, 'msg'=>'查询/更新/删除条件需为数组类型', 'data'=>[]];
		}

		try {
			$res = $tabObj->deleteAll($where);
			return ['status'=>0, 'msg'=>'ok', 'data'=>['affected'=>$res]];
		} catch (\Exception $e) {
			if(preg_match("/Unknown\s+column\s+'(.*)'\s+in/i", $e->getMessage(), $matches)){
				$status = 1054;
				$msg    = "未知的字段名:{$matches[1]}";
			}else{
				$status = $e->getCode();
				$msg    = $e->getMessage();
			}
			return ['status'=>$status, 'msg'=>$msg, 'data'=>[]];
			
		}
		
	}

	/**
	 * 【假删】删除指定条件数据
	 * @param object $tabObj   表对象
	 * @param string $pkid     主键Id值
	 * @return array 返回数组  返回实际影响行数
	 * @author martinzhang
	 */
	public static function deleteFalse($tabObj, $where){
		return self::updateByWhere($tabObj, ['isdeleted'=>'1'], $where);
	}

	/**
	 * 更新数据(通过条件)
	 * @param  object $tabObj    表对象
	 * @param  array $arrParams  字段参数(要更新为的字段=>值)
	 * @param  array $where      更新条件
	 * @return array 返回数组    返回实际影响行数
	 * @author martinzhang
	 */
	public static function updateByWhere($tabObj, $arrParams, $where){
		if(!is_array($arrParams)){
			return ['status'=>11, 'msg'=>'查询/更新/删除条件需为数组类型', 'data'=>[]];
		}
		if(!is_array($where)){
			return ['status'=>11, 'msg'=>'查询/更新/删除条件需为数组类型', 'data'=>[]];
		}
		
		//有效性检查
		try {
			foreach($arrParams as $k=>$v){
				if($v===''){
					$arrParams[$k] = NULL;	//无视空值
				}else{
					$arrParams[$k] = trim($v);
				}
			}			
			
		} catch (\Exception $e) {
			return ['status'=>$e->getCode(), 'msg'=>$e->getMessage(), 'data'=>[]];
		}
		
		//尝试更新
		try {
			$res=$tabObj->updateAll($arrParams, $where);
			return ['status'=>0, 'msg'=>'ok', 'data'=>['affected'=>$res]];			
	
		} catch (\Exception $e) {
			if(preg_match("/Unknown\s+column\s+'(.*)'\s+in/i", $e->getMessage(), $matches)){				
				$status = 1054;
				$msg    = "未知的字段名:{$matches[1]}";
			}else{
				$status = $e->getCode();
				$msg    = $e->getMessage();
			}
			return ['status'=>$status, 'msg'=>$msg, 'data'=>[]];
		}
			
	}

	/**
	 * 按主键Id更新一条数据
	 * @param object $tabObj     表对象
	 * @param array  $arrParams  字段参数
	 * @param int    $pkid       主键值
	 * @return array 返回数组    成功返回实际影响行数恒=1
	 * @author martinzhang
	 */
	public static function updateByPkid($tabObj, $arrParams, $pkid){
		//按主键查询此条数据
		$rowObj = $tabObj->findOne($pkid);
		if($rowObj==null){
			return ['status'=>7, 'msg'=>'此条数据不存在', 'data'=>[]];
		}
	
		//拼装数据对象属性值
		try {
			foreach($arrParams as $k=>$v){
				if($v===''){					
					$rowObj->$k = NULL;	//无视空值
				}else{
					$rowObj->$k = trim($v);
				}
			}				
		
		} catch (\Exception $e) {
			if(preg_match("/Setting\s+unknown\s+property:.*::(.*?)$/i", $e->getMessage(), $matches)){
				$status = 1363;
				$msg    = "字段名{$matches[1]}未知";
			}else{
				$status = $e->getCode();
				$msg    = $e->getMessage();
			}
			return ['status'=>$status, 'msg'=>$msg, 'data'=>[]];			
		}

		//尝试保存
		try {
			$res = $rowObj->save();	//注：这里返回的实际是更新结果布尔值 true/false
			if($res==true){
				//更新成功
				return ['status'=>0, 'msg'=>'ok', 'data'=>['affected'=>1]];
			}else{
				//更新失败
				return ['status'=>9, 'msg'=>'数据更新失败', 'data'=>[]];
			}
	
		} catch (\Exception $e) {
			return ['status'=>$e->getCode(), 'msg'=>$e->getMessage(), 'data'=>[]];
		}
			
	}

	
	/**
	 * 查询数据条数
	 * @param object $tabObj    表对象
	 * @param array  $where     条件
	 * @param string $fl        需要显示字段
	 * @param bool   $reqsql    是否打印SQL语句
	 * @return int              返回统计数值：-1表示出错，0或正值表示正常
	 * @author martinzhang
	 */
	public static function findCount($tabObj, $where, $reqsql=false){
		try {
			//查询数据列表
			$query = $tabObj->find();
			$query->where($where);
			$count = $query->count();
			if($reqsql==true){
				echo $query->createCommand()->getRawSql()."<br />\n";
			}
				
			return $count;
				
		} catch (\Exception $e) {
			return -1;
		}
	
	}


	/**
	 * 查询单条数据
	 * @param object $tabObj    表对象
	 * @param array  $where     条件
	 * @param string $fl        需要显示字段
	 * @param string $orderby   排序方式
	 * @param bool   $reqsql    是否打印SQL语句
	 * @return array            有结果返回数组，无结果返回null
	 * @author martinzhang
	 */
	public static function findOne($tabObj, $where, $fl='', $orderby='', $reqsql=false){
		try {
			//查询数据列表
			$query = $tabObj->find()->select($fl);			
			$query->where($where);
			$row = $query->offset(0)->limit(1)->orderBy($orderby)->asArray()->one();
			if($reqsql==true){
				echo $query->createCommand()->getRawSql()."<br />\n";
			}
			if($row != null){
				//过虑null字段值
				foreach($row as &$v){
					if($v==null){
						$v = '';
					}
				}
			}
			
			return $row;
			
		} catch (\Exception $e) {
			if(preg_match("/Unknown\s+column\s+'(.*)'\s+in/i", $e->getMessage(), $matches)){
				$status = 1054;
				$msg    = "未知的字段名:{$matches[1]}";
			}else{
				$status = $e->getCode();
				$msg    = $e->getMessage();
			}
			return ['status'=>$status, 'msg'=>$msg, 'data'=>[]];			
		}
		
	}


	/**
	 * 查询多条数据
	 * @param object $tabObj    表对象
	 * @param array  $where     条件
	 * @param int    $pagesize  每页数量
	 * @param int    $page      当前页
	 * @param string $orderby   排序
	 * @param string $fl        需要显示字段
	 * @param bool   $reqsql    是否打印SQL语句，true打印；false不打印(默认)
	 * @return array            返回查询结果
	 * @author martinzhang
	 */
	public static function findAll($tabObj, $where, $pagesize=99999999, $page=1, $orderby='', $fl='', $reqsql=false){
		$pagesize  = trim($pagesize)=='' ? 99999999 : $pagesize;
		$page      = trim($page)=='' ? 1 : $page;
		try {
			//获取总条数，进行分页计算
			$total   = $tabObj->find()->where($where)->count();
			$divPage = ZTools::divPage($total, $pagesize, $page);
			//$this->p($divPage);exit;
			
			//查询数据列表
			$query = $tabObj->find()->select($fl);			
			$query->where($where);
			$list = $query->offset($divPage['offset'])->limit($divPage['length'])->orderBy($orderby)->asArray()->all();			
			if($reqsql==true){
				echo $query->createCommand()->getRawSql().'<br />';
			}
			if(empty($list) || $list==null){
				$list = [];
			}else{
				//过虑null字段值
				foreach($list as &$row){
					foreach($row as &$v){
						if($v==null){
							$v = '';
						}
					}
				}
			}
			
			return ['status'=>0, 'msg'=>'ok', 'data'=>['divPage'=>$divPage, 'list'=>$list]];
			
		} catch (\Exception $e) {
			if(preg_match("/Unknown\s+column\s+'(.*)'\s+in/i", $e->getMessage(), $matches)){
				$status = 1054;
				$msg    = "未知的字段名:{$matches[1]}";
			}else{
				$status = $e->getCode();
				$msg    = $e->getMessage();
			}
			return ['status'=>$status, 'msg'=>$msg, 'data'=>[]];			
		}
		
	}
	
	/**
	 * 查询多条数据(方式2)
	 * @param object $tabObj    表对象
	 * @param array  $where     条件
	 * @param int    $offset    查询起始值(偏移量)
	 * @param int    $limit     查询条数
	 * @param string $orderby   排序
	 * @param string $fl        需要显示字段
	 * @param bool   $reqsql    是否打印SQL语句，true打印；false不打印(默认)
	 * @return array            返回查询结果
	 * @author martinzhang
	 */
	public static function findAll2($tabObj, $where, $offset=0, $limit=99999999, $orderby='', $fl='', $reqsql=false){
		$offset = trim($offset)=='' ? 0 : $offset;
		$limit  = trim($limit)=='' ? 99999999 : $limit;		
		try {
			//获取总条数，进行分页计算
			$total   = $tabObj->find()->where($where)->count();
			
			//查询数据列表
			$query = $tabObj->find()->select($fl);
			$query->where($where);
			$list = $query->offset($offset)->limit($limit)->orderBy($orderby)->asArray()->all();
			if($reqsql==true){
				echo $query->createCommand()->getRawSql().'<br />';
			}
			if(empty($list) || $list==null){
				$list = [];
			}else{
				//过虑null字段值
				foreach($list as &$row){
					foreach($row as &$v){
						if($v==null){
							$v = '';
						}
					}
				}
			}
				
			return ['status'=>0, 'msg'=>'ok', 'data'=>['total'=>$total, 'list'=>$list]];
				
		} catch (\Exception $e) {
			if(preg_match("/Unknown\s+column\s+'(.*)'\s+in/i", $e->getMessage(), $matches)){
				$status = 1054;
				$msg    = "未知的字段名:{$matches[1]}";
			}else{
				$status = $e->getCode();
				$msg    = $e->getMessage();
			}
			return ['status'=>$status, 'msg'=>$msg, 'data'=>[]];
		}
	
	}

	/**
	 * 同步将MySQL表某行数据同步到MongoDB某集合
	 * @param object $tabObj          MySQL表对象
	 * @param int    $pkId            主键值
	 * @param string $mongoCollection Mongodb集合名
	 * @param string $mongoHost       本次要连接的mongo数据库主机
	 * @param string $mongoDbName     本次要操作的mongo数据库名(仅当默认数据库未设置时，此选项才起作用)
	 * @return array 返回数组                       返回同步到mongodb中的主键id
	 * @author martinzhang
	 */
	public static function rsyncSave2Monogdb($tabObj, $pkId, $mongoCollection, $mongoHost='mongodb1', $mongoDbName=''){
		//MySQL主键名称
		$pkName = $tabObj->primaryKey()[0];
	
		//从MySQL中查询此条新插入数据
		$new = $tabObj->find()->where([$pkName => $pkId])->asArray()->one();
		if($new==null){
			return ['status'=>6, 'msg'=>'MySQL中此条待同步数据不存在', 'data'=>[]];
		}
		
		//处理数据类型
		foreach($new as &$v){
			if(trim($v)==''){
				$v=(string)'';
				continue 1;
			}
			if(is_numeric($v)){
				//$v=(int)$v;	//备用
			}
		}		
		if(array_key_exists('sort', $new)){
			$new['sort'] = (int)$new['sort'];
		}
		$new['_id'] = (int)$pkId;
		
		//存放入Mongodb
		$save =CommonMongoDB::save($mongoCollection, $new, $mongoHost, $mongoDbName);
		if($save['data']['pkid']==''){
			//如果缓存失败，记入失败日志
			$mongodb  = \Yii::$app->get($mongoHost);
			if(!empty($mongodb->defaultDatabaseName)){
				$mongodb_tabname = $mongodb->defaultDatabaseName;
			}elseif(!empty($mongodb->options['db'])){
				$mongodb_tabname = $mongodb->options['db'];
			}
			$mongodb_tabname = trim($mongodb->dsn, '/').'/'.$mongodb_tabname;
			LogCacheFailed::insertMongodbLog4Write($tabObj, $pkId, $mongodb_tabname, $mongoCollection);
		}
		return $save;
	}

	/**
	 * 同步从MySQL和Mongodb中删除数据 - ByPkids
	 * @param object  $tabObj           MySQL表对象
	 * @param string  $pkIds            主键值Ids
	 * @param string  $mongoCollection  Mongodb集合名
	 * @param string  $mongoHost        本次要连接的mongo数据库主机
	 * @param string  $mongoDbName      本次要操作的mongo数据库名(仅当默认数据库未设置时，此选项才起作用)
	 * @return array  返回数组          返回影响行数
	 * @author martinzhang
	 */
	public static function rsyncDeleteTrueByPkids($tabObj, $pkIds, $mongoCollection, $mongoHost='mongodb1', $mongoDbName=''){
		//MySQL主键名称
		$pkName = $tabObj->primaryKey()[0];
		$pkIds  = ZTools::fmtArrayFilter($pkIds);
		
		//初始化本次操作结果
		$initResult = true;
		
		//开启事务
		$transaction = \Yii::$app->db->beginTransaction();
		
		try {
			//对MySQL执行物理删除
			$resMysql = self::deleteTrue($tabObj, ['in', $pkName, $pkIds]);
			if($resMysql['status']==0 && $resMysql['msg']=='ok'){
				//对Mongodb执行删除
				$resMongodb = CommonMongoDB::deleteTrue($mongoCollection, ['in', '_id', ZTools::fmtArray2StringOrInteger($pkIds,'int')], $mongoHost, $mongoDbName);
				if($resMongodb['status']!=0 || $resMongodb['msg']!='ok'){
					//如果缓存失败，记入失败日志
					$mongodb  = \Yii::$app->get($mongoHost);
					if(!empty($mongodb->defaultDatabaseName)){
						$mongodb_tabname = $mongodb->defaultDatabaseName;
					}elseif(!empty($mongodb->options['db'])){
						$mongodb_tabname = $mongodb->options['db'];
					}
					$mongodb_tabname = trim($mongodb->dsn, '/').'/'.$mongodb_tabname;
					LogCacheFailed::insertMongodbLog4Write($tabObj, 0, $mongodb_tabname, $mongoCollection, '删除数据失败,pkids:'.@implode(',', $pkIds));
					
					//回滚事务
					$initResult = false;
					$transaction->rollBack();
					
				}else{
					//提交事务
					$transaction->commit();
				}
				
				
			}else{
				//回滚事务
				$initResult = false;
				$transaction->rollBack();
			}
			
		} catch (\Exception $e) {
			//回滚事务
			$initResult = false;
			$transaction->rollBack();
		}		
		
		if($initResult == false){
			$resMysql['data']['affected']=0;
		}
		
		return ZTools::response($resMysql);
				
	}

	/**
	 * 同步从MySQL和Mongodb中删除数据 - ByWhere
	 * @param object  $tabObj           MySQL表对象
	 * @param array   $where            删除条件
	 * @param string  $mongoCollection  Mongodb集合名
	 * @param string  $mongoHost        本次要连接的mongo数据库主机
	 * @param string  $mongoDbName      本次要操作的mongo数据库名(仅当默认数据库未设置时，此选项才起作用)
	 * @return array  返回数组          返回影响行数
	 * @author martinzhang
	 */
	public static function rsyncDeleteTrueByWhere($tabObj, $where, $mongoCollection, $mongoHost='mongodb1', $mongoDbName=''){
		//初始化本次操作结果
		$initResult = true;
		
		//开启事务
		$transaction = \Yii::$app->db->beginTransaction();
		
		try {
			//对MySQL执行物理删除
			$resMysql = self::deleteTrue($tabObj, $where);
			if($resMysql['status']==0 && $resMysql['msg']=='ok'){
				//对Mongodb执行删除
				$resMongodb = CommonMongoDB::deleteTrue($mongoCollection, $where, $mongoHost, $mongoDbName);
				if($resMongodb['status']!=0 || $resMongodb['msg']!='ok'){
					//如果缓存失败，记入失败日志
					$mongodb  = \Yii::$app->get($mongoHost);
					if(!empty($mongodb->defaultDatabaseName)){
						$mongodb_tabname = $mongodb->defaultDatabaseName;
					}elseif(!empty($mongodb->options['db'])){
						$mongodb_tabname = $mongodb->options['db'];
					}
					$mongodb_tabname = trim($mongodb->dsn, '/').'/'.$mongodb_tabname;
					LogCacheFailed::insertMongodbLog4Write($tabObj, 0, $mongodb_tabname, $mongoCollection, '删除数据失败,where:'.json_encode($where));
					
					//回滚事务
					$initResult = false;
					$transaction->rollBack();
					
				}else{
					//提交事务
					$transaction->commit();
				}
				
				
			}else{
				//回滚事务
				$initResult = false;
				$transaction->rollBack();
			}
			
		} catch (\Exception $e) {
			//回滚事务
			$initResult = false;
			$transaction->rollBack();			
		}

		if($initResult == false){
			$resMysql['data']['affected']=0;
		}
		
		return ZTools::response($resMysql);
		
	}

	/**
	 * 同步将MySQL表某行数据同步到Solr集合
	 * @param object $tabObj         MySQL表对象
	 * @param int    $pkId           MySQL主键值
	 * @param string $solrCollection Solr中的集合名称
	 * @param string $fmtTimeFiles   需要特殊格式化的时间字段名，用逗号分隔，格式: $fmtTimeFiles = 'field1,field2';
	 * @return boolean true|false
	 * @author martinzhang
	 */
	public static function rsyncSave2Solr($tabObj, $pkId, $solrCollection, $fmtTimeFiles=''){
		//MySQL主键名称
		$pkName = $tabObj->primaryKey()[0];
	
		//从MySQL中查询此条新插入数据
		$new = $tabObj->find()->where([$pkName => $pkId])->asArray()->one();
		if($new==null){
			return ['status'=>6, 'msg'=>'MySQL中此条待同步数据不存在', 'data'=>[]];
		}
		
		//格式化特殊时间字段
		if(!empty($fmtTimeFiles)){
			$newTimeFiles = ZTools::fmtArrayFilter($fmtTimeFiles);			
			if(!empty($newTimeFiles)){				
				foreach($newTimeFiles as $val){
					if(array_key_exists($val, $new)){
						$new[$val] = ZTools::fmtSolrTime($new[$val]);
					}
				}
			}
		}		
		//ZTools::p($new);

		try{
			//执行保存入solr
			$solr = new Solr($solrCollection);
			$save = $solr->save($new);
			//ZTools::p($save);
		
			if($save['status']!=0 || $save['msg']!='ok'){
				//如果缓存失败，记入失败日志
				LogCacheFailed::insertSolrLog4Write($tabObj, $pkId, $solrCollection, '向solr保存数据失败');
				return false;
			}else{
				return true;
			}
		
		}catch (\Exception $e){
			//如果缓存失败，记入失败日志
			LogCacheFailed::insertSolrLog4Write($tabObj, $pkId, $solrCollection, $e->getMessage());
			return false;
		}
	}
	
	/**
	 * 同步从MySQL和Solr中删除数据 - ByPkids
	 * @param object  $tabObj           MySQL表对象
	 * @param string  $pkIds            主键值Ids
	 * @param string  $solrCollection   Solr集合名
	 * @return array  返回数组                          返回影响行数
	 * @author martinzhang
	 */
	public static function rsyncDelSolrTrueByPkids($tabObj, $pkIds, $solrCollection){
		//MySQL主键名称
		$pkName = $tabObj->primaryKey()[0];
		$pkIds  = ZTools::fmtArrayFilter($pkIds);
	
		//初始化本次操作结果
		$initResult = true;
		
		//开启事务
		$transaction = \Yii::$app->db->beginTransaction();
	
		try {
			//对MySQL执行物理删除
			$resMysql = self::deleteTrue($tabObj, ['in', $pkName, $pkIds]);
			if($resMysql['status']==0 && $resMysql['msg']=='ok'){
				//从solr中删除
				$solr    = new Solr($solrCollection);
				$delSolr = $solr->deleteByPkIds($pkIds);
				//ZTools::p($delSolr);
				
				if($delSolr['status']!=0 || $delSolr['msg']!='ok'){					
					//回滚事务
					$initResult = false;
					$transaction->rollBack();
					
				}else{
					//提交事务
					$transaction->commit();
				}
	
	
			}else{
				//回滚事务
				$initResult = false;
				$transaction->rollBack();
			}
				
		} catch (\Exception $e) {
			//回滚事务
			$initResult = false;
			$transaction->rollBack();
		}
	
		if($initResult == false){
			$resMysql['data']['affected']=0;
		}
		
		return ZTools::response($resMysql);
		
	}

	/**
	 * 同步从MySQL和Solr中删除数据 - ByWhere
	 * @param object  $tabObj           MySQL表对象
	 * @param array   $where            MySQL删除条件
	 * @param array   $query            Solr删除条件
	 * @param string  $solrCollection   Solr集合名
	 * @return array  返回数组          返回影响行数
	 * @author martinzhang
	 */
	public static function rsyncDelSolrTrueByWhere($tabObj, $where, $query, $solrCollection){
		//初始化本次操作结果
		$initResult = true;
	
		//开启事务
		$transaction = \Yii::$app->db->beginTransaction();
	
		try {
			//对MySQL执行物理删除
			$resMysql = self::deleteTrue($tabObj, $where);
			if($resMysql['status']==0 && $resMysql['msg']=='ok'){
				//从solr中删除
				$solr    = new Solr($solrCollection);
				$delSolr = $solr->deleteByQuery($query);
				//ZTools::p($delSolr);				

				if($delSolr['status']!=0 || $delSolr['msg']!='ok'){						
					//回滚事务
					$initResult = false;
					$transaction->rollBack();
						
				}else{
					//提交事务
					$transaction->commit();
				}
	
	
			}else{
				//回滚事务
				$initResult = false;
				$transaction->rollBack();
			}
				
		} catch (\Exception $e) {
			//回滚事务
			$initResult = false;
			$transaction->rollBack();
		}
	
		if($initResult == false){
			$resMysql['data']['affected']=0;
		}
	
		return ZTools::response($resMysql);
		
	}	


	

}
